#!/usr/bin/env python3

import sys
from tempfile import mkstemp
from shutil import move
from os import remove, close
def replace(file_path, pattern, subst, count):
    #Create temp file
    fh, abs_path = mkstemp()
    new_file = open(abs_path,'w')
    old_file = open(file_path)

    for line in old_file:
        new_file.write(line.replace(pattern, subst, count))
    #close temp file
    new_file.close()
    close(fh)
    old_file.close()
    #Remove original file
    remove(file_path)
    #Move new file
    move(abs_path, file_path)

def reReplace(file_path, repattern, subst, count):
    import re
    #Create temp file
    fh, abs_path = mkstemp()
    new_file = open(abs_path,'w')
    old_file = open(file_path)
    p = re.compile(repattern)
    for line in old_file:
        if p.search(line):
          new_file.write(p.sub(subst,line,count))
        else:
          new_file.write(line)
    #close temp file
    new_file.close()
    close(fh)
    old_file.close()
    #Remove original file
    remove(file_path)
    #Move new file
    move(abs_path, file_path)

import fileinput
def insertLine(file_path, lineIndex, subst):
    #Create temp file
    fh, abs_path = mkstemp()
    new_file = open(abs_path,'w')
    old_file = open(file_path)
    fi = fileinput.input(file_path,inplace=1)
    done = False
    for line in fi :
      if (done==False) and (fi.filelineno()== lineIndex) :
        done = True
        new_file.write(line)
        new_file.write(subst)
      else:
        new_file.write(line)
    fi.close()

    #close temp file
    new_file.close()
    close(fh)
    old_file.close()
    #Remove original file
    remove(file_path)
    #Move new file
    move(abs_path, file_path)

def insertPattern(file_path, rePattern, subst):
    import re
    #Create temp file
    fh, abs_path = mkstemp()
    new_file = open(abs_path,'w')
    old_file = open(file_path)
    fi = fileinput.input(file_path,inplace=1)
    p = re.compile(rePattern)
    done = False
    for line in fi :
      if (done==False) and p.search(line) :
        done = True
        print(done)
        new_file.write(line)
        new_file.write(subst)
      else:
        new_file.write(line)
    fi.close()

    #close temp file
    new_file.close()
    close(fh)
    old_file.close()
    #Remove original file
    remove(file_path)
    #Move new file
    move(abs_path, file_path)

def checkPattern(file_path, rePattern):
    import re
    #Create temp file
    p = re.compile(rePattern)
    fi = fileinput.input(file_path,inplace=1)
    done = False
    for line in fi :
      if (done==False) and p.search(line) :
        done = True
    fi.close()
    return done


from subprocess import call
from subprocess import Popen
def setDevCs(swug):
        swugf=None
        if swug == 'dch':
            swugf = 'dch'
        elif swug == 'eul':
            swugf = 'eul'
        elif swug== 'hs':
            swugf = 'hs'
        elif swug == 'ultch' or swug == 'ulcch' or swug == 'uldch':
            swugf = 'rxm'

        print("======>>"+"set dev CS for swug:"+swug)
        try:
            retcode = call("/proj/CoolTools/bin/cs_init " + " -s" + swugf +  " -t" + " dev", shell=True)
            if retcode < 0:
                print(">>"+"Child was terminated by signal", -retcode, file=sys.stderr)
            else:
                print(">>"+"Child returned", retcode, file=sys.stderr)
        except OSError as e:
            print(">>"+"Execution failed:", e, file=sys.stderr)

def setCs(cs):
    print("======>>"+"set cs :"+cs)
    try:
        retcode = call("cleartool setcs " +cs, shell=True)
        if retcode < 0:
            print(">>"+"Child was terminated by signal", -retcode, file=sys.stderr)
        else:
            print(">>"+"Child returned", retcode, file=sys.stderr)
    except OSError as e:
        print(">>"+"Execution failed:", e, file=sys.stderr)

def addLmcBranch2Cs(cs,lmcBranch):
    print("======>>"+"edit cs to include your LMC branch ")

    #if os.path.exists("tmp.txt"):
    #    retcode = call("rm -f " + "tmp.txt", shell=True)
    #call("cleartool lstype -short -kind brtype -invob /vobs/rbs/bb/delivery > tmp.txt", shell=True)
    #if(checkPattern("tmp.txt",lmcBranch) == False):
    #    call("cleartool mkbrtype -nc "+lmcBranch,shell = True)
    #if os.path.exists("tmp.txt"):
    #    retcode = call("rm -f " + "tmp.txt", shell=True)

    #always try to create lmcbranch, if it already exist
    print("======>>"+"create lmcBranch :"+lmcBranch)
    try:
        retcode = call("cleartool mkbrtype -nc "+lmcBranch,shell = True)
        if retcode < 0:
            print(">>"+"Child was terminated by signal", -retcode, file=sys.stderr)
        else:
            print(">>"+"Child returned", retcode, file=sys.stderr)
    except OSError as e:
        print(">>"+"Execution failed:", e, file=sys.stderr)



    devBranch = "element * .../"+lmcBranch+"/LATEST\n"
    checkedout ="element * CHECKEDOUT\n"
    mkBranch = "mkbranch "+lmcBranch+"\n"

    pattern = r"# ([TR]XM)|(BB) Load Module Container"
    insertPattern(cs,pattern,mkBranch)
    insertPattern(cs,pattern,devBranch)
    insertPattern(cs,pattern,checkedout)

def addLmBranch2Cs(cs,lmBranches):
    print("======>>"+"edit cs to include your LMs branch ")
    pattern = r"# ([TR]XM)|(BB) Load Module Container"
    for lmBranch in lmBranches:
        devBranch = "element * .../"+lmBranch+"/LATEST\n"
        insertPattern(cs,pattern,devBranch)



def buildLmc(makefile,makefilePath):
    print("======>>"+"build LMC")
    parentDir = os.getcwd()
    os.chdir(makefilePath)
    buildCwd = os.getcwd()
    try:

        retcode = call("clearmake -f "+makefile +" -C gnu ", shell=True,cwd = buildCwd)

        if retcode < 0:
            print(">>"+"Child was terminated by signal", -retcode, file=sys.stderr)
        else:
            print(">>"+"Child returned", retcode, file=sys.stderr)
    except OSError as e:
        print(">>"+"Execution failed:", e, file=sys.stderr)
    os.chdir(parentDir)

def lockLabel(label):
    print("======>>"+"lock label "+label)
    try:
        retcode = call("cleartool lock lbtype:"+label, shell=True)
        if retcode < 0:
            print(">>"+"Child was terminated by signal", -retcode, file=sys.stderr)
        else:
            print(">>"+"Child returned", retcode, file=sys.stderr)
    except OSError as e:
        print(">>"+"Execution failed:", e, file=sys.stderr)



def label(targetLmcLabel,files):
    print("======>>"+"label modified files with target Label "+ targetLmcLabel)
    try:
        retcode1 = call("cleartool mklbtype -nc " + targetLmcLabel, shell=True)
        retcode2 = call("cleartool mklabel  " + targetLmcLabel+ "  " +files , shell=True)
        retcode = retcode1 & retcode2
        if retcode < 0:
            print(">>"+"Child was terminated by signal", -retcode, file=sys.stderr)
        else:
            print(">>"+"Child returned", retcode, file=sys.stderr)
    except OSError as e:
        print(">>"+"Execution failed:", e, file=sys.stderr)


def setDeliveryCs(deliveryCs):
    print("======>>"+"set updated delivery.cs")
    try:
        retcode = call("cleartool setcs " + deliveryCs, shell=True)
        if retcode < 0:
            print(">>"+"Child was terminated by signal", -retcode, file=sys.stderr)
        else:
            print(">>"+"Child returned", retcode, file=sys.stderr)
    except OSError as e:
        print(">>"+"Execution failed:", e, file=sys.stderr)

def ctcifile(files):
    print("======>>"+"check in all modified files ")
    try:
        retcode = call("cleartool ci -nc " + files, shell=True)
        if retcode < 0:
            print(">>"+"Child was terminated by signal", -retcode, file=sys.stderr)
        else:
            print(">>"+"Child returned", retcode, file=sys.stderr)
    except OSError as e:
        print(">>"+"Execution failed:", e, file=sys.stderr)


def ctcofile(files):
    print("======>>"+"check out "+files)
    try:
        retcode = call("cleartool co -nc " + files, shell=True)
        if retcode < 0:
            print(">>"+"Child was terminated by signal", -retcode, file=sys.stderr)
        else:
            print(">>"+"Child returned", retcode, file=sys.stderr)
    except OSError as e:
        print(">>"+"Execution failed:", e, file=sys.stderr)

def ctuncofile(files):
    print("======>>"+"check out "+files)
    try:
        retcode = call("cleartool unco  " + files, shell=True)
        if retcode < 0:
            print(">>"+"Child was terminated by signal", -retcode, file=sys.stderr)
        else:
            print(">>"+"Child returned", retcode, file=sys.stderr)
    except OSError as e:
        print(">>"+"Execution failed:", e, file=sys.stderr)


def saveCs(cs):
    print("======>>"+"save cs: "+cs)
    try:
        retcode = call("cleartool catcs  > " + cs , shell=True)
        if retcode < 0:
            print(">>"+"Child was terminated by signal", -retcode, file=sys.stderr)
        else:
            print(">>"+"Child returned", retcode, file=sys.stderr)
    except OSError as e:
        print(">>"+"Execution failed:", e, file=sys.stderr)

def checkBranchExistance(branchType):

    print("======>>"+"checkBranchExistance: "+branchType)
    try:
        if retcode < 0:
            print(">>"+"Child was terminated by signal", -retcode, file=sys.stderr)
        else:
            print(">>"+"Child returned", retcode, file=sys.stderr)
    except OSError as e:
        print(">>"+"Execution failed:", e, file=sys.stderr)


def rmfile(files):
    print("======>>"+"rm file: "+files)
    try:
        if os.path.exists(files):
            retcode = call("rm -f " + files, shell=True)
            if retcode < 0:
                print(">>"+"Child was terminated by signal", -retcode, file=sys.stderr)
            else:
                print(">>"+"Child returned", retcode, file=sys.stderr)
    except OSError as e:
        print(">>"+"Execution failed:", e, file=sys.stderr)





import os
def buildLMC(args):
    """
    build LMC with args from stdin
    """
    print(args.swug[0])
    setDevCs(args.swug[0])

    lmcDir = "/vobs/rbs/bb/delivery/dp/"+args.hwgen[0] +"/"+args.track[0]+"/"+args.lmc[0]+"_lmc/"
    makefileDir = "/vobs/rbs/bb/delivery/dp/"+args.hwgen[0] +"/"+args.track[0]+"/"+args.lmc[0]+"_lmc"
    if (args.lmc[0] == 'txm') or (args.lmc[0] == 'rxm'):
        baselineLmcCs = lmcDir+"delivery.cs@@/main/ln1/" + args.baselineLmcLabel[0]
    else:
        baselineLmcCs = lmcDir+"bb_lmc_delivery.cs@@/main/ln1/" + args.baselineLmcLabel[0]



    setCs(baselineLmcCs)

    tempCsFile = lmcDir+"temp.cs"
    saveCs(tempCsFile)

    addLmBranch2Cs(tempCsFile,args.lmBranch)
    addLmcBranch2Cs(tempCsFile,args.lmcBranch[0])

    setCs(tempCsFile)
    rmfile(tempCsFile)

    deliveryCsFile = None
    if args.hwgen[0] == 'duw1':
        deliveryCsFile = lmcDir+"delivery.cs "
    else:
        deliveryCsFile = lmcDir+"bb_lmc_delivery.cs "

    ctcofile(deliveryCsFile)
    saveCs(deliveryCsFile)

    binfiles = lmcDir + args.lmc[0]+"_lmc.bin "
    hdrfiles = lmcDir + args.lmc[0]+"_lmc.hdr "

    ctcofile(binfiles+hdrfiles)

    makefile = lmcDir+"Makefile"
    buildLmc(makefile,makefileDir)

    ctcifile(deliveryCsFile+binfiles+hdrfiles)


    ctuncofile(deliveryCsFile+hdrfiles)

    label(args.targetLmcLabel[0],binfiles)
    lockLabel(args.targetLmcLabel[0])

def main():
    from argparse import ArgumentParser
    from argparse import ArgumentDefaultsHelpFormatter
    parser = ArgumentParser(\
            description = 'Build LMC automatically for DUW.\
            available hwgen and track shall follow latest /vobs/rbs/bb/delivery/dp \
            contents,note: -hwgen and -hw is same,  -hw is just for short of -hwgen',\
            formatter_class = ArgumentDefaultsHelpFormatter\
            )
    parser.add_argument('-version', '-v',action = 'version', version = '%(prog)s 1.0')
    parser.add_argument('-hw', '--hwgen', nargs = 1, type = str, default = ['duw1'], dest = 'hwgen', choices = ['duw1', 'duw2'], help = 'Hardware Generation')
    parser.add_argument('-t', '--track',nargs = 1, type = str, default = ['main'], dest = 'track', choices = ['main', 'w11a', 'w11b', 'w12a', 'w12b', 'w13a', 'w13b'], help = 'the product track for which you want to build LMC' )
    parser.add_argument('-lmc', nargs = 1, type = str, default = ['txm'], dest = 'lmc', choices = ['txm', 'rxm','bb','urbs'], help = 'txm(duw1) or rmx(duw1), bb(duw2) ' )
    parser.add_argument('-sw', nargs = 1, type = str, default = ['dch'], dest = 'swug', choices = ['dch', 'eul', 'hs', 'ultch', 'ulcch', 'uldch'], help = 'the software unit  name' )
    parser.add_argument('-bl', '--baseLabel', nargs = 1, type = str, required = True, dest = 'baselineLmcLabel', metavar = '<CXP9013412-XXXX> | <CXP9013811-XXXX>', help = 'bb_lmc looks like CXP9020608-XXXX, txm_lmc:: looks like CXP9013412-XXXX while for rxm_lmc:: looks like CXP9013811-XXXX, the Baseline LMC Label check BBIV cs_gen for detail, e.g.  CXP9013412-R15U')
    parser.add_argument('-blm', '--branchLm', type = str, nargs = '+', required = True, dest = 'lmBranch', metavar = '<xjiashe_black_lm>',  help = 'the Branch contain black LMs,signature and "_lm" subfix is recommended')
    parser.add_argument('-blmc', '--branchLmc', nargs = 1, type = str, required = True, dest = 'lmcBranch', metavar = '<xjiashe_black_lm>',  help = 'the Branch contain black LMs: ,signature and "_lmc" subfix is recommended')
    parser.add_argument('-tl', '--targetLabel', nargs = 1, type = str, required = True, dest = 'targetLmcLabel', metavar = '<CXP9013412-XXXXnnn> | <CXP9013811-XXXXnnn>',help = 'bb_lmc looks like CXP9020608-XXXXnnn, txm_lmc:: looks like CXP9013412-XXXXnnn while for rxm_lmc:: looks like CXP9013811-XXXXnnn, e.g. CXP9013412-R15U001, the Target Label which will send back to BBIV, naming convention is prefered to be a derived version from Baseline Label with nnn subfix')
    args = parser.parse_args()
    buildLMC(args)



if __name__ == "__main__":
  main()
